﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using SCEM.DTO;
using SCEM.CompraProdutos;

namespace SCEMService
{
    [ServiceContract(Namespace = "http://SCEM.Services")]
    interface ISCEM
    {
        #region CRUD Produto

        /// <summary>
        /// Salva um novo produto no banco de dados.
        /// </summary>
        /// <param name="produtoDTO">Um DTO representando o novo produto a ser gravado no banco.</param>
        /// <returns>Um DTO representando o produto gravado no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        ProdutoDTO SaveProduto(ProdutoDTO produtoDTO);

        /// <summary>
        /// Atualiza um produto no banco de dados.
        /// </summary>
        /// <param name="produtoDTO">Um DTO representando o produto a ser atualizado no banco.</param>
        /// <returns>Um DTO representando o produto atualizado no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        ProdutoDTO UpdateProduto(ProdutoDTO produtoDTO);

        /// <summary>
        /// Recupera um produto do banco de dados.
        /// </summary>
        /// <param name="idProduto">A identificação do produto que se deseja recuperar.</param>
        /// <returns>Um DTO representando o produto procurado ou <code>null</code> caso o produto não possa ser localizado ou caso ocorra um erro.</returns>
        [OperationContract]
        ProdutoDTO GetProduto(string idProduto);

        /// <summary>
        /// Recupera um subconjunto de todas os produtos para exibição em um formato paginado.
        /// </summary>
        /// <param name="pageNumber">O número da página (>= 1).</param>
        /// <param name="resultsPerPage">A quantidade de resultados a serem exibidos por página.</param>
        /// <param name="includeDisabledEntities"><code>true</code> para incluir produtos desativados, <code>false</code> caso contrário.</param>
        /// <returns></returns>
        [OperationContract]
        List<ProdutoDTO> GetProdutos(int pageNumber, int resultsPerPage, bool includeDisabledEntities);

        /// <summary>
        /// Retorna o total de produtos cadastrados.
        /// </summary>
        /// <param name="includeDisabledEntities"><code>true</code> para incluir produtos desativados, <code>false</code> caso contrário.</param>
        /// <returns>O total de produtos cadastrados.</returns>
        [OperationContract]
        int GetTotalProdutos(bool includeDisabledEntities);

        /// <summary>
        /// Desativa um produto no banco de dados.
        /// </summary>
        /// <param name="idProduto">O id do produto a ser desativado.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool DisableProduto(string idProduto);

        #endregion

        #region Listagem de TipoProduto

        /// <summary>
        /// Busca e retorna a lista de todos os tipos de produtos cadastrados no sistema.
        /// </summary>
        /// <returns>A lista de todos os tipos de produtos cadastrados no sistema.</returns>
        [OperationContract]
        List<TipoProdutoDTO> ListarTiposProdutos();

        #endregion

        #region Listagem de TipoFisioterapia

        /// <summary>
        /// Busca e retorna a lista de todos os tipos de fisioterapia cadastrados no sistema.
        /// </summary>
        /// <returns>A lista de todos os tipos de fisioterapia cadastrados no sistema.</returns>
        [OperationContract]
        List<TipoFisioterapiaDTO> ListarTiposFisioterapia();

        #endregion

        #region CRUD Fornecedor

        /// <summary>
        /// Salva um novo fornecedor no banco de dados.
        /// </summary>
        /// <param name="fornecedorDTO">Um DTO representando o novo fornecedor a ser gravado no banco.</param>
        /// <returns>Um DTO representando o fornecedor gravado no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        FornecedorDTO SaveFornecedor(FornecedorDTO fornecedorDTO);

        /// <summary>
        /// Atualiza um fornecedor no banco de dados.
        /// </summary>
        /// <param name="fornecedorDTO">Um DTO representando o fornecedor a ser atualizado no banco.</param>
        /// <returns>Um DTO representando o fornecedor atualizado no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        FornecedorDTO UpdateFornecedor(FornecedorDTO fornecedorDTO);

        /// <summary>
        /// Recupera um fornecedor do banco de dados.
        /// </summary>
        /// <param name="idFornecedor">A identificação do fornecedor que se deseja recuperar.</param>
        /// <returns>Um DTO representando o fornecedor procurado ou <code>null</code> caso o fornecedor não possa ser localizado ou caso ocorra um erro.</returns>
        [OperationContract]
        FornecedorDTO GetFornecedor(string idFornecedor);

        /// <summary>
        /// Recupera um subconjunto de todos os fornecedores para exibição em um formato paginado.
        /// </summary>
        /// <param name="pageNumber">O número da página (>= 1).</param>
        /// <param name="resultsPerPage">A quantidade de resultados a serem exibidos por página.</param>
        /// <param name="includeDisabledEntities"><code>true</code> para incluir fornecedores desativados, <code>false</code> caso contrário.</param>
        /// <returns></returns>
        [OperationContract]
        List<FornecedorDTO> GetFornecedores(int pageNumber, int resultsPerPage, bool includeDisabledEntities);

        /// <summary>
        /// Retorna o total de fornecedores cadastrados.
        /// </summary>
        /// <param name="includeDisabledEntities"><code>true</code> para incluir fornecedores desativados, <code>false</code> caso contrário.</param>
        /// <returns>O total de fornecedores cadastrados.</returns>
        [OperationContract]
        int GetTotalFornecedores(bool includeDisabledEntities);

        /// <summary>
        /// Desativa um fornecedor no banco de dados.
        /// </summary>
        /// <param name="idFornecedor">O id do fornecedor a ser desativado.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool DisableFornecedor(string idFornecedor);

        #endregion

        #region CRUD Equipamento

        /// <summary>
        /// Salva um novo equipamento no banco de dados.
        /// </summary>
        /// <param name="equipamentoDTO">Um DTO representando o novo equipamento a ser gravado no banco.</param>
        /// <returns>Um DTO representando o equipamento gravado no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        EquipamentoDTO SaveEquipamento(EquipamentoDTO equipamentoDTO);

        /// <summary>
        /// Atualiza um equipamento no banco de dados.
        /// </summary>
        /// <param name="equipamentoDTO">Um DTO representando o equipamento a ser atualizado no banco.</param>
        /// <returns>Um DTO representando o equipamento atualizado no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        EquipamentoDTO UpdateEquipamento(EquipamentoDTO equipamentoDTO);

        /// <summary>
        /// Recupera um equipamento do banco de dados.
        /// </summary>
        /// <param name="idEquipamento">A identificação do equipamento que se deseja recuperar.</param>
        /// <returns>Um DTO representando o equipamento procurado ou <code>null</code> caso o equipamento não possa ser localizado ou caso ocorra um erro.</returns>
        [OperationContract]
        EquipamentoDTO GetEquipamento(string idEquipamento);

        /// <summary>
        /// Recupera um subconjunto de todos os equipamentos para exibição em um formato paginado.
        /// </summary>
        /// <param name="pageNumber">O número da página (>= 1).</param>
        /// <param name="resultsPerPage">A quantidade de resultados a serem exibidos por página.</param>
        /// <param name="includeDisabledEntities"><code>true</code> para incluir equipamentos desativados, <code>false</code> caso contrário.</param>
        /// <returns></returns>
        [OperationContract]
        List<EquipamentoDTO> GetEquipamentos(int pageNumber, int resultsPerPage, bool includeDisabledEntities);

        /// <summary>
        /// Retorna o total de equipamentos cadastrados.
        /// </summary>
        /// <param name="includeDisabledEntities"><code>true</code> para incluir equipamentos desativados, <code>false</code> caso contrário.</param>
        /// <returns>O total de equipamentos cadastrados.</returns>
        [OperationContract]
        int GetTotalEquipamentos(bool includeDisabledEntities);

        /// <summary>
        /// Desativa um equipamento no banco de dados.
        /// </summary>
        /// <param name="idEquipamento">O id do equipamento a ser desativado.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool DisableEquipamento(string idEquipamento);

        #endregion

        #region Controle Estoque

        /// <summary>
        /// Insere uma quantidade do produto no estoque.
        /// </summary>
        /// <param name="idProduto">O id do produto a ser inserido no estoque.</param>
        /// <param name="quantidade">A quantidade a ser inserida do produto.</param>
        /// <returns>Retorna 0 caso sucesso, -1 caso ocorra um erro no banco.</returns>
        [OperationContract]
        int InsereProdutoEstoque(string idProduto, int quantidade);

        /// <summary>
        /// SERVIÇO PEDIDO PELA FÁBRICA 9 - USO DE ESTOQUE
        /// Retira uma quantidade do produto no estoque
        /// </summary>
        /// <param name="idProduto">O id do produto a ser retirado do estoque.</param>
        /// <param name="quantidade">A quantidade a ser retirada do produto.</param>
        /// <returns> Retorna 0 caso sucesso, retorna -1 caso quantidade retirada é maior que a quantidade existente no estoque (não é alterada a quantidade do produto), retorna -2 erro banco.</returns>
        [OperationContract]
        int RetiraProdutoEstoque(string idProduto, int quantidade);

        /// <summary>
        /// Lista os produtos cuja quantidade existente no estoque é menor que a quantidade mínima do produto. 
        /// </summary>
        /// <param name="pageNumber">O número da página >= 1.</param>
        /// <param name="resultsPerPage">Quantidade de resultados a serem exibidos por página.</param>
        /// <returns>A lista de produtos que satisfazem a condição.</returns>
        [OperationContract]
        List<ProdutoDTO> ListaProdutosAlerta(int pageNumber, int resultsPerPage);

        /// <summary>
        /// SERVIÇO PEDIDO PELO BUENO
        /// Lista os produtos cuja quantidade existente no estoque é maior que 0. 
        /// </summary>
        /// <param name="pageNumber">O número da página >= 1.</param>
        /// <param name="resultsPerPage">Quantidade de resultados a serem exibidos por página.</param>
        /// <returns>A lista de produtos que satisfazem a condição.</returns>
        [OperationContract]
        List<ProdutoDTO> ListaProdutosEstoque(int pageNumber, int resultsPerPage);

        /// <summary>
        /// Verifica se o produto está disponível no estoque (quantidade > 0).
        /// </summary>
        /// <param name="idProduto">O id do produto cuja disponibilidade deseja ser verificada.</param>
        /// <returns><code>true</code> se o produto está disponível, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool VerificaDisponibilidadeProduto(string idProduto);

        /// <summary>
        /// SERVIÇO PEDIDO PELO BUENO
        /// Serviço oferecido que retorna uma lista com o histórico do estoque em um determinado período escolhido pelo usuário.
        /// </summary>
        /// <param name="idProduto">A identificação do produto.</param>
        /// <param name="dataInicio">Data inicial a ser considerada.</param>
        /// <param name="dataFim">Data final a ser considerada.</param>
        /// <param name="pageNumber">Número da página.</param>
        /// <param name="resultsPerPage">Quantidade de resultados por página.</param>
        /// <returns>Os itens do histórico requisitados pelo usuário.</returns>
        [OperationContract]
        List<HistoricoEstoqueDTO> BuscarHistoricoProdutos(string idProduto, DateTime dataInicio, DateTime dataFim, int pageNumber, int resultsPerPage);

        #endregion

        #region Compra Produtos

        /// <summary>
        /// Salva uma nova condição de venda no banco de dados.
        /// </summary>
        /// <param name="dto">O DTO representando a nova condição de venda a ser gravada.</param>
        /// <returns>Um DTO representando a entidade gravada no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        CondicaoVendaDTO SaveCondicaoVenda(CondicaoVendaDTO dto);

        /// <summary>
        /// Atualiza uma condição de venda no banco de dados.
        /// </summary>
        /// <param name="dto">O DTO representando a condição de venda a ser atualizada no banco.</param>
        /// <returns>Um DTO representando a condição de venda atualizada no banco ou <code>null</code> em caso de erro.</returns>
        [OperationContract]
        CondicaoVendaDTO UpdateCondicaoVenda(CondicaoVendaDTO dto);

        /// <summary>
        /// Exclui uma condição de venda do banco de dados.
        /// </summary>
        /// <param name="idProduto">A identificação do produto.</param>
        /// <param name="idFornecedor">A identificação do fornecedor.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool DeleteCondicaoVenda(string idProduto, string idFornecedor);

        /// <summary>
        /// Recupera uma condição de venda do banco de dados.
        /// </summary>
        /// <param name="idProduto">A identificação do produto.</param>
        /// <param name="idFornecedor">A identificação do fornecedor.</param>
        /// <returns>Um DTO representando a condição de venda procurada, ou <code>null</code> caso a condição não possa ser localizada 
        /// ou caso ocorra um erro de comunicação com o banco de dados.</returns>
        [OperationContract]
        CondicaoVendaDTO GetCondicaoVenda(string idProduto, string idFornecedor);

        /// <summary>
        /// Recupera todas as condições de venda de determinado produto.
        /// </summary>
        /// <param name="idProduto">A identificação do produto.</param>
        /// <returns>Uma lista contendo todas as condições de venda associadas ao produto fornecido.</returns>
        [OperationContract]
        List<CondicaoVendaDTO> GetAllCondicoesVenda(string idProduto);

        /// <summary>
        /// Cria uma nova ordem de compra de produto e a salva no banco de dados se ela for autorizada pelo financeiro.
        /// </summary>
        /// <param name="dto">O DTO representando a nova ordem de compra de produto a ser gravada no banco de dados.</param>
        /// <returns>Um DTO representando a ordem de compra de produto gravada no banco, ou <code>null</code> caso o financeiro não autorize
        /// ou caso ocorra um erro.</returns>
        [OperationContract]
        OrdemCompraProdutoDTO CreateOrdemCompraProduto(OrdemCompraProdutoDTO dto);

        /// <summary>
        /// Atualiza o status de uma ordem de compra de produto no banco de dados.
        /// Ordens de compra no estado CANCELADO ou FINALIZADO não podem ser alteradas.
        /// Além disso, ao se cancelar uma ordem de compra, é necessário disparar uma requisição para o financeiro para cancelar a transação.
        /// </summary>
        /// <param name="idOrdemCompraProduto">O id da ordem de compra de produto cujo status deseja-se atualizar.</param>
        /// <param name="novoStatus">O novo status dessa ordem de compra de produto.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool UpdateOrdemCompraProdutoStatus(string idOrdemCompraProduto, StatusOrdemCompra novoStatus);

        #endregion

        #region Compra Equipamentos

        /// <summary>
        /// Cria uma nova ordem de compra de equipamento e a salva se for aprovada pelo financeiro
        /// </summary>
        /// <param name="dto">O DTO da ordem de compra a ser criada</param>
        /// <param name="equipamentoDTO">O DTO do equipamento já salvo</param>
        /// <returns>o DTO salvo ou <code>null</code> em caso de erro ou não aprovação do financeiro</returns>
        [OperationContract]
        OrdemCompraEquipamentoDTO CreateOrdemCompraEquipamento(OrdemCompraEquipamentoDTO dto, EquipamentoDTO equipamentoDTO);

        /// <summary>
        /// Atualiza o status da ordem de compra de equipamento retornando <code>true</code>
        /// caso bem sucedido ou <code>false</code> caso contrário
        /// </summary>
        /// <param name="idOrdemCompraEquipamento">id da ordem de compra do  equipamento</param>
        /// <param name="novoStatus">novo status</param>
        /// <returns>Boolean indicando o sucesso da operação</returns>
        [OperationContract]
        bool UpdateOrdemCompraEquipamentoStatus(string idOrdemCompraEquipamento, StatusOrdemCompra novoStatus);

        #endregion

        #region Manutencao

        /// <summary>
        /// Busca e retorna a quantidade de equipamentos disponíveis para determinado tipo de fisioterapia em um dia dado.
        /// </summary>
        /// <param name="tipoFisioterapiaId">A identificação do tipo de fisioterapia para o qual se deseja saber a quantidade de equipamentos disponíveis.</param>
        /// <param name="diaConsulta">Um DateTime contendo o dia que se deseja consultar.</param>
        /// <returns>A quantidade garantida de equipamentos disponíveis para determinado tipo de fisioterapia no dia selecionado.</returns>
        [OperationContract]
        int VerificarQuantidadeEquipamentosDisponiveis(string tipoFisioterapiaId, DateTime diaConsulta);

        /// <summary>
        /// Busca e retorna uma lista contendo todos os equipamentos que devem ter sua manutenção preventiva realizada em menos de 30 dias, sendo 
        /// que essa manutenção preventiva ainda não foi agendada.
        /// </summary>
        /// <returns>Uma lista contendo todos os equipamentos que satisfaçam essa condição.</returns>
        [OperationContract]
        List<EquipamentoDTO> ListarEquipamentosAlertaManutencao();

        /// <summary>
        /// Busca e retorna uma lista contendo todos os equipamentos que possuem uma manutenção preventiva agendada.
        /// </summary>
        /// <returns>Uma lista contendo todos os equipamentos que possuam uma manutenção preventina agendada.</returns>
        [OperationContract]
        List<EquipamentoDTO> ListarEquipamentosManutencaoPreventinaAgendada();

        /// <summary>
        /// Agenda a manutenção preventiva de um dado equipamento. Caso esse equipamento já possua uma manutenção preventiva agendada, é
        /// considerado que o usuário deseja realizar um reagendamento.
        /// </summary>
        /// <param name="equipamentoId">O identificação do equipamento para o qual se deseja agendar ou reagendar uma manutenção preventiva.</param>
        /// <param name="dataManutencao">A data da manutenção preventiva.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso contrário.</returns>
        [OperationContract]
        bool AgendarManutencaoPreventiva(string equipamentoId, DateTime dataManutencao);

        /// <summary>
        /// Arquiva a manutenção preventiva associada a um determinado equipamento.
        /// </summary>
        /// <param name="equipamentoId">A identificação do equipamento cuja manutenção preventiva deseja-se arquivar.</param>
        /// <param name="descricao">Uma descrição para essa entrada no histórico.</param>
        /// <returns><code>true</code> em caso de sucesso, <code>false</code> caso esse equipamento não tenha nenhuma manutenção preventiva para ser arquivada.</returns>
        [OperationContract]
        bool ArquivarManutencaoPreventiva(string equipamentoId, string descricao);

        #endregion


    }
}
